import package_util as pu
import socket

from bound_check import *
from extract_background import extract_background
from bound_check import predict_one_request
from keras.preprocessing import image
from multiprocessing import Process
import multiprocessing as mul
import argparse


from yolo_hat import YOLO_HAT
from yolo_tempt import YOLO_TEMPT
from yolo_bike import YOLO_BIKE
from yolo_face import YOLO_FACE
from yolo_bin import YOLO_BIN

import threading
import time
from PIL import Image
from PIL import ImageFile
from image_util import *
ImageFile.LOAD_TRUNCATED_IMAGES = True
from crop_image import crop_image,get_points,get_region_num,points_filter
import os
from keras.models import load_model
import os
import tensorflow as tf
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
from keras.backend.tensorflow_backend import set_session
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.9
set_session(tf.Session(config=config))
SERVER_PORT=7999
FLAGS = None
OPERATION_DIR="./yjjy_tempt"
STORAGE_DIR="yjjy_tempt/"

def get_time_stamp():
    ct = time.time()
    local_time = time.localtime(ct)
    data_head = time.strftime("%Y-%m-%d %H:%M:%S", local_time)
    data_secs = (ct - int(ct)) * 1000
    time_stamp = "%s.%03d" % (data_head, data_secs)
    #print(time_stamp)
    stamp = ("".join(time_stamp.split()[0].split("-")) + "".join(time_stamp.split()[1].split(":"))).replace('.', '')
    #print(stamp)
    return stamp

class Predict_OBJ:
    def __init__(self):
        parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
        FLAGS = parser.parse_args()

        # handle_pipe(pipe[1])


        yolo_0 = YOLO_TEMPT(**vars(FLAGS))
        yolo_1 = YOLO_BIKE(**vars(FLAGS))
        yolo_2 = YOLO_FACE(**vars(FLAGS))
        yolo_3 = YOLO_BIN(**vars(FLAGS))
        yolo_4 = YOLO_HAT(**vars(FLAGS))




        self.yolo_0 = yolo_0
        self.yolo_1 = yolo_1
        self.yolo_2 = yolo_2
        self.yolo_3 = yolo_3
        self.yolo_4 = yolo_4


    def detect_img(self, model_num, time_stamp):

        # img = pipe.recv()
        # msg = .recv()
        # print(type(msg))
        # model_num = int(msg[-3:])

        # 检查图片有效性
        # CHK_COMPLETE = check_image_valid(img)

        # secene_id 解析场景编号，决定调用具体的模型
        # if secene_id==X：
        #     》>》>》

        # if CHK_COMPLETE:

        # print("type",type(model_num))
        # print(model_num)
        image_path=time_stamp+".jpg"
        if model_num == 101:
            img = image_path
            # print("img:", img)
            try:
                image = Image.open(img)
            except:
                image = Image.open("error.jpg")
            # print("loaded")
            # print("image:", img)
            request = self.yolo_1.detect_image(image)
            print("predicting image>>>>>>>>", img,"<<<<<<<<<")
            os.remove(img)
            # print("predicted>>")

            return request
        if model_num == 104:
            img = image_path
            # print("img:",img)
            try:
                image = Image.open(img)
            except:
                image = Image.open("error.jpg")
                print('Open Error! Try again!')
                # pipe.send(img+"不存在！")
            # print("loaded")
            # img = msg[:-3]
            # print("image:", img)
            request_face = self.yolo_2.detect_image_2(image)
            print("predicting image>>>>>>>>", img,"<<<<<<<<<")
            os.remove(img)
            # print("predicted>>")

            # print(request_face)
            # print(request_face=="")

            if request_face == "":
                a = ""
                return a

            else:

                request_hat = self.yolo_4.detect_image(image)

                request = request_hat + request_face

                return request

        if model_num == 110:
            img = image_path

            try:
                image = Image.open(img)
            except:
                image = Image.open("error.jpg")
                print('Open Error! Try again!')
                # pipe.send(img+"不存在！")

            print("predicting image>>>>>>>>", img,"<<<<<<<<<")
            os.remove(img)
            request = self.yolo_3.detect_image_3(image)
            return request
        if model_num == 113:
            img = image_path

            try:
                image = Image.open(img)
            except:
                image = Image.open("error.jpg")
                print('Open Error! Try again!')
                # pipe.send(img+"不存在！")

            print("predicting image>>>>>>>", img,"<<<<<<<")
            os.remove(img)
            request = self.yolo_0.detect_image(image)
            return request


class YYJY:
    def __init__(self):
        bound_check = get_bound_check_model()
        self.bound_check = bound_check
    def dectect_yjjy(self,region_num,time_crr):

        #region_num = int(msg[:-20])
        #time_crr = msg[-20:-3]
        request = predict_one_request(self.bound_check, region_num=region_num, time=time_crr)
        return request

def get_img_size(image_path):

    try:
        image_size=[]
        image = Image.open(image_path)
        image_size=list(image.size)
    except:

        image_size = [1920,1080]
        print("open error ,set default values.")

    return image_size

def handle_single_package(request_data,client_socket,obj_det,yjjy_obj):

    print("receiving package contents:>>>>>", request_data)

    image_path = pu.get_package_json_value_by_key(request_data, "imagePath")
    ipc_id = pu.get_package_json_value_by_key(request_data, "ipcId")
    message_id = pu.get_package_json_value_by_key(request_data, "messageId")

    process_list = pu.get_package_json_value_by_key(request_data, "model")
    request_dic = {}
    request_dic["image_path"] = image_path
    request_dic["ipc_id"] = ipc_id
    request_dic["message_id"] = message_id

    yjjy_params = {}
    # 设置放缩的图片分辨率
    #if image_path not in camera_dic:
    ####current_image_size = get_img_size(image_path)
    #    camera_dic[ipc_id] = current_image_size
    image_size =get_img_size(image_path)
    print("<<",ipc_id,"'s image_size:",image_size,">>>>>>>>>")
    #image_size = [1920, 1080]
    crop_image_size = []
    crop_image_cord = []
    server_result_dic = {}

    IF_SEND_OBJ_DETECT_PACKAGE = False
    IF_SEND_YJJY_DETECT_PACKAGE = False

    # 循环处里一个请求包的不同请求
    time_stamp = get_time_stamp()

    for box_dic in process_list:

        model_num = box_dic["modelId"]
        print("model_id>>>>", model_num,"<<<<<<<<<<<<<")
        if model_num in [104, 110, 101, 113]:
            #print("box_dic;", box_dic)

            IF_SEND_OBJ_DETECT_PACKAGE = True
            # scene_id=box_dic["sceneId"]
            scene_id = model_num
            # print("croping image>>>>>>")
            # print(box_dic)
            # print("1")
            # >>>
            crop_image_size.append(int((box_dic["xLength"] / 1000 * image_size[0])))
            crop_image_size.append(int(box_dic["yLength"] / 1000 * image_size[1]))
            crop_image_cord.append(int(box_dic["leftX"] / 1000 * image_size[0]))
            crop_image_cord.append(int(box_dic["leftY"] / 1000 * image_size[1]))
            # image_size=crop_img_percentage(get_percentage_list(box_dic),image_path)
            # print("2")
            # >>>
            crop_img_percentage(get_percentage_list(box_dic), image_path,time_stamp)
            # print("3")
            # 同时发送场景编号>>>>>>>>>>......>>>>>>
            #pipe.send(  time_stamp + ".jpg"+ str(model_num))

            print(time_stamp +".jpg was generated image by:"+image_path+ " using  model %s to predict  >>>>>>>>>"%(str(model_num)))

            # print("4")
            result = obj_det.detect_img(model_num, time_stamp)
            # 完善处理结果的逻辑，把result中crop图片的xywh转换为整体图片的xywh
            print("return_result:>>>>>>>>>>>>>>>>>>>>>>>>>>> "+result+"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
            # >>>
            result_ = pu.trans_crop_box_params(image_size, crop_image_cord, result)
            #print("result_", result_)
            server_result_dic[scene_id] = result_
            # print(result_)

            # print(server_result_dic)

        if model_num == 106:
            # print(box_dic)
            IF_SEND_YJJY_DETECT_PACKAGE = True
            time.sleep(1)
            print("processing bound check request>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
            # delete_trash()
            name_list = box_dic["nameList"]
            absolute_path = box_dic["parentPath"]
            image_path_list = []
            for path in name_list:
                image_path_list.append(os.path.join(absolute_path, path))

            points = points_filter(get_points(box_dic,image_size))

            region_num = get_region_num(points)

            print("region_num:", region_num)

            time_ = get_time_stamp()
            #ty
            os.mkdir(os.path.join(STORAGE_DIR, time_))

            for i in range(region_num):
                j = 0

                for image_path in image_path_list:
                    crop_image(points[i], image_path, name_list[j], i, time_,image_size)
                    j += 1

            extract_background(region_num=region_num, time=time_)

            print("extract_background finished>>>>>>")


            #pipe.send(str(region_num) + time_ + str(model_num))
            result=yjjy_obj.dectect_yjjy(region_num,time_)
            #os.rmdir(os.path.join(STORAGE_DIR, time_))
            print("predict complete ,delete current directory>>>>>")
            #result = pipe.recv()
            identify_list = result
            # server_result_package_yjjy = pu.generate_package_yjjy(request_dic,identify_list,model_num)
            yjjy_params["identify_list"] = identify_list
            yjjy_params["model_num"] = model_num
            # print(server_result_package)

    # send package>>>>
    if IF_SEND_OBJ_DETECT_PACKAGE:
        server_result_package = pu.generate_package(request_dic, server_result_dic)
        print("return obj detect message>>>>>>>>>>>>>>>>")
        print(server_result_package)
        client_socket.send(server_result_package)

    if IF_SEND_YJJY_DETECT_PACKAGE:
        # request_dic,identify_list,model_id
        server_result_package_yjjy = pu.generate_package_yjjy(request_dic, yjjy_params["identify_list"],
                                                              yjjy_params["model_num"])
        print("return yjjy message>>>>>>>>>>>>>>>%s"%(server_result_package_yjjy))
        #print(server_result_package_yjjy)
        client_socket.send(server_result_package_yjjy)



def handle_single_package_1(request_data,client_socket,obj_det,yjjy_obj):

    print("receiving package contents:>>>>>", request_data)

    image_path = pu.get_package_json_value_by_key(request_data, "imagePath")
    ipc_id = pu.get_package_json_value_by_key(request_data, "ipcId")
    message_id = pu.get_package_json_value_by_key(request_data, "messageId")

    process_list = pu.get_package_json_value_by_key(request_data, "model")
    request_dic = {}
    request_dic["image_path"] = image_path
    request_dic["ipc_id"] = ipc_id
    request_dic["message_id"] = message_id

    yjjy_params = {}
    # 设置放缩的图片分辨率
    #if image_path not in camera_dic:
    ####current_image_size = get_img_size(image_path)
    #    camera_dic[ipc_id] = current_image_size
    image_size =get_img_size(image_path)
    print("<<",ipc_id,"'s image_size:",image_size,">>>>>>>>>")
    #image_size = [1920, 1080]
    crop_image_size = []
    crop_image_cord = []
    server_result_dic = {}

    IF_SEND_OBJ_DETECT_PACKAGE = False
    IF_SEND_YJJY_DETECT_PACKAGE = False

    # 循环处里一个请求包的不同请求
    time_stamp = get_time_stamp()

    for box_dic in process_list:

        model_num = box_dic["modelId"]
        print("model_id>>>>", model_num,"<<<<<<<<<<<<<")
        if model_num in [104, 110, 101, 113]:
            #print("box_dic;", box_dic)

            IF_SEND_OBJ_DETECT_PACKAGE = True
            # scene_id=box_dic["sceneId"]
            scene_id = model_num
            # print("croping image>>>>>>")
            # print(box_dic)
            # print("1")
            # >>>
            crop_image_size.append(int((box_dic["xLength"] / 1000 * image_size[0])))
            crop_image_size.append(int(box_dic["yLength"] / 1000 * image_size[1]))
            crop_image_cord.append(int(box_dic["leftX"] / 1000 * image_size[0]))
            crop_image_cord.append(int(box_dic["leftY"] / 1000 * image_size[1]))
            # image_size=crop_img_percentage(get_percentage_list(box_dic),image_path)
            # print("2")
            # >>>
            crop_img_percentage(get_percentage_list(box_dic), image_path,time_stamp)
            # print("3")
            # 同时发送场景编号>>>>>>>>>>......>>>>>>
            #pipe.send(  time_stamp + ".jpg"+ str(model_num))

            print(time_stamp +".jpg was generated image by:"+image_path+ " using  model %s to predict  >>>>>>>>>"%(str(model_num)))

            # print("4")
            result = obj_det.detect_img(model_num, time_stamp)
            # 完善处理结果的逻辑，把result中crop图片的xywh转换为整体图片的xywh
            print("return_result:>>>>>>>>>>>>>>>>>>>>>>>>>>> "+result+"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
            # >>>
            result_ = pu.trans_crop_box_params(image_size, crop_image_cord, result)
            #print("result_", result_)
            server_result_dic[scene_id] = result_
            # print(result_)

            # print(server_result_dic)

        if model_num == 106:
            # print(box_dic)
            IF_SEND_YJJY_DETECT_PACKAGE = True
            time.sleep(1)
            print("processing bound check request>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
            # delete_trash()
            name_list = box_dic["nameList"]
            absolute_path = box_dic["parentPath"]

            points = points_filter(get_points(box_dic,image_size))

            region_num = get_region_num(points)

            print("region_num:", region_num)



            print("extract_background finished>>>>>>")


            result=[]

            for i in range(region_num):
                result.append(0)
            #result=yjjy_obj.dectect_yjjy(region_num,time_)
            #os.rmdir(os.path.join(STORAGE_DIR, time_))
            #print("predict complete ,delete current directory>>>>>")
            #result = pipe.recv()
            identify_list = result
            # server_result_package_yjjy = pu.generate_package_yjjy(request_dic,identify_list,model_num)
            yjjy_params["identify_list"] = identify_list
            yjjy_params["model_num"] = model_num
            # print(server_result_package)

    # send package>>>>
    if IF_SEND_OBJ_DETECT_PACKAGE:
        server_result_package = pu.generate_package(request_dic, server_result_dic)
        print("return obj detect message>>>>>>>>>>>>>>>>")
        print(server_result_package)
        client_socket.send(server_result_package)

    if IF_SEND_YJJY_DETECT_PACKAGE:
        # request_dic,identify_list,model_id
        server_result_package_yjjy = pu.generate_package_yjjy(request_dic, yjjy_params["identify_list"],
                                                              yjjy_params["model_num"])
        print("return yjjy message>>>>>>>>>>>>>>>%s"%(server_result_package_yjjy))
        #print(server_result_package_yjjy)
        client_socket.send(server_result_package_yjjy)

def handle_client(client_socket,obj_det,yjjy_obj):

    """

    处理客户端请求

    """
    request_stack = []
    while True:
        request_data=pu.get_one_package(client_socket)

        threading.Thread(target=handle_single_package_1, args=(request_data,client_socket,obj_det,yjjy_obj)).start()




def server():

    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(("", SERVER_PORT))
    server_socket.listen(128)
    obj_det = Predict_OBJ()
    yjjy_obj = YYJY()
    #camera size dictionary
    #camera_dic ={}

    while True:
        client_socket, client_address = server_socket.accept()
        #print(client_socket)
        #print("[%s]用户连接上了" % (client_address))
        print("use connect>>>")
        threading.Thread(target=handle_client, args=(client_socket,obj_det,yjjy_obj,)).start()







if __name__ == '__main__':
    server()
    #Process(target=server, args=(obj_det, yjjy_obj)).start()
    #threading.Thread(target=server, args=(obj_det, yjjy_obj)).start()
    #detect_img(pipe[1],yolo_0,yolo_1,yolo_2,yolo_3,yolo_4,bound_check)
    #detect_img(pipe[1], yolo_0, yolo_1, yolo_2, yolo_3)

    # detect_img(YOLO(**vars(FLAGS)),pipe[1])
    # detect_img(YOLO_2(**vars(FLAGS)),pipe[1])
